import { Injectable, Optional } from '@nestjs/common';
import { eq, and, ilike, inArray, notInArray } from 'drizzle-orm';
import { BaseService, db, sysUser, type SysUser, sysUserRole, sysRole } from '@nbase/db';
import { BizException, CacheKeyFactory, CacheService, CryptoUtil } from '@nbase/nest-mods';
import { SYSTEM_ROLE, type IPaginationResponse, type IUser } from '@nbase/shared';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { QueryUserDto } from './dto/query-user.dto';
import { AssignRolesDto } from './dto/assign-roles.dto';
import { toUser, toUserPage } from './user.mapper';

/**
 * 用户服务
 * 使用 BaseService 自动处理审计字段
 */
@Injectable()
export class UserService extends BaseService<typeof sysUser> {
  constructor(
    @Optional() private readonly cacheService?: CacheService
  ) {
    super(sysUser);
  }

  /**
   * 根据用户名查找（用于认证等内部逻辑，保留密码等字段）
   */
  async findByUsername(username: string): Promise<SysUser | null> {
    const user = await this.findOne(eq(sysUser.username, username));
    return (user ?? null) as SysUser | null;
  }

  /**
   * 根据 ID 获取用户详情（用于对外接口）
   */
  async getUserById(id: string): Promise<IUser> {
    const user = (await this.findById(id)) as SysUser | undefined;
    if (!user) {
      throw BizException.userNotFound();
    }
    return toUser(user);
  }

  /**
   * 创建用户（重写以添加密码加密）
   */
  async createUser(createUserDto: CreateUserDto): Promise<IUser> {
    const hashedPassword = await CryptoUtil.hashPassword(createUserDto.password);

    const created = await this.create({
      ...createUserDto,
      password: hashedPassword,
    });

    return toUser(created as SysUser);
  }

  /**
   * 更新用户（重写以添加密码加密）
   */
  async updateUser(id: string, updateUserDto: UpdateUserDto): Promise<IUser> {
    const updateData: Record<string, unknown> = { ...updateUserDto };

    if (updateUserDto.password) {
      updateData.password = await CryptoUtil.hashPassword(updateUserDto.password);
    }

    const updated = await this.update(id, updateData);
    return toUser(updated as SysUser);
  }

  /**
   * 删除用户
   */
  async deleteUser(id: string): Promise<void> {
    // 检查用户是否拥有超级管理员角色
    const userRoles = await db
      .select({ roleCode: sysRole.code })
      .from(sysUserRole)
      .innerJoin(sysRole, eq(sysUserRole.roleId, sysRole.id))
      .where(eq(sysUserRole.userId, id));

    const hasSuperAdmin = userRoles.some((r) => r.roleCode === SYSTEM_ROLE.SUPER_ADMIN);
    if (hasSuperAdmin) {
      throw BizException.operationFailed('拥有超级管理员角色的用户是系统内置用户，不允许删除');
    }

    await this.softDelete(id);
  }

  /**
   * 重置用户密码为默认值 123456
   */
  async resetPassword(id: string): Promise<void> {
    const user = await this.findById(id);
    if (!user) {
      throw BizException.userNotFound();
    }

    const hashedPassword = await CryptoUtil.hashPassword('123456');

    await this.update(id, {
      password: hashedPassword,
    });
  }


  /**
   * 分页查询用户（对外返回 IUser）
   *
   * @param query 分页查询参数
   */
  async paginateUsers(query: QueryUserDto): Promise<IPaginationResponse<IUser>> {
    const conditions = [];

    // 根据用户名关键词筛选
    if (query.username) {
      conditions.push(ilike(sysUser.username, `%${query.username}%`));
    }

    // 根据昵称关键词筛选
    if (query.nickname) {
      conditions.push(ilike(sysUser.nickname, `%${query.nickname}%`));
    }

    // 根据状态筛选
    if (query.status !== undefined) {
      conditions.push(eq(sysUser.status, query.status));
    }

    // 查询拥有 super_admin 角色的用户 ID 列表
    const superAdminUsers = await db
      .select({ userId: sysUserRole.userId })
      .from(sysUserRole)
      .innerJoin(sysRole, eq(sysUserRole.roleId, sysRole.id))
      .where(eq(sysRole.code, SYSTEM_ROLE.SUPER_ADMIN));

    const superAdminUserIds = superAdminUsers.map((u) => u.userId);

    // 过滤掉拥有 super_admin 角色的用户
    if (superAdminUserIds.length > 0) {
      conditions.push(notInArray(sysUser.id, superAdminUserIds));
    }

    const where = conditions.length > 0 ? and(...conditions) : undefined;
    const result = await this.paginate(query, where);
    return toUserPage(result as IPaginationResponse<SysUser>);
  }

  /**
   * 为用户分配角色
   */
  async assignRoles(userId: string, assignRolesDto: AssignRolesDto): Promise<void> {
    // 检查用户是否存在
    const user = await this.findById(userId);
    if (!user) {
      throw BizException.userNotFound();
    }

    // 检查是否包含超级管理员角色
    if (assignRolesDto.roleIds.length > 0) {
      const roles = await db
        .select({ code: sysRole.code })
        .from(sysRole)
        .where(inArray(sysRole.id, assignRolesDto.roleIds));

      const hasSuperAdmin = roles.some((r) => r.code === SYSTEM_ROLE.SUPER_ADMIN);
      if (hasSuperAdmin) {
        throw BizException.operationFailed('超级管理员角色是系统内置角色，不允许手动分配给用户');
      }
    }

    const currentUserId = this.getUserId();

    // 使用事务：先删除旧角色，再添加新角色
    await db.transaction(async (tx) => {
      await tx.delete(sysUserRole).where(eq(sysUserRole.userId, userId));

      if (assignRolesDto.roleIds.length > 0) {
        const values = assignRolesDto.roleIds.map((roleId) => ({
          userId,
          roleId,
          createdBy: currentUserId,
        }));
        await tx.insert(sysUserRole).values(values);
      }
    });

    // 清除用户权限缓存
    if (this.cacheService) {
      await this.cacheService.del(CacheKeyFactory.userPermissions(userId));
      await this.cacheService.del(CacheKeyFactory.userRoles(userId));
    }
  }

  /**
   * 获取用户的角色（角色 ID 列表）
   */
  async getUserRoles(userId: string): Promise<string[]> {
    const userRoles = await db
      .select({
        roleId: sysUserRole.roleId,
      })
      .from(sysUserRole)
      .where(eq(sysUserRole.userId, userId));

    return userRoles.map((ur) => ur.roleId);
  }
}
